# include "Game.h"

# include "Renderer.h"
# include "GUI.h"
# include "AI.h"
# include "EventListener.h"

# include "World.h"

# include "Hero.h"
# include "Map.h"
# include "Obstacle.h"
# include "Enemy.h"
# include "PNJ.h"

Game::Game() : myRenderer( 0), myGUI( 0), myAI( 0)
{
	myRenderer = new Renderer( this);
	myGUI = new GUI( this);
	myAI = new AI( this);
	myEventListener = new EventListener( this);
	myWorld = new World();
}

Game::~Game()
{

}

void Game::init()
{
	if ( !myRenderer->init( myGUI, myAI, myEventListener) )
	{
		return;
	}

	if ( !myGUI->init( myRenderer) )
	{
		return;
	}

	myEventListener->init( myRenderer, myGUI, myAI);

	myAI->init( myRenderer, myGUI);

	myWorld->init( this, myRenderer, myAI, myGUI);

	Event evtTmp;
	evtTmp.message = CREATE_MENU;

	myGUI->receiveEvent( evtTmp);
	myState = MENU_STATE;

	startRendering();
}

void Game::receiveEvent( const Event evt)
{
	myEvents.push( evt);
}

void Game::createNewGame()
{
	myState = GAME_STATE;

	myWorld->setCurrentWorld( "0");
	myWorld->loadWorld( "Demo1");

	myAI->setWorld( myWorld);
	myAI->loadWorld( "Demo1");

	myGUI->setWorld( myWorld);
	myEventListener->setWorld( myWorld);
}

void Game::changeWorld( const std::string name)
{
	myAI->unloadWorld();
	myWorld->unloadWorld();
	myWorld->loadWorld( name);
	myAI->loadWorld( name);
}

void Game::central( Ogre::Real time)
{
	handleEvents();
	
	switch ( myState )
	{
		case MENU_STATE:
		case GUI_STATE:
		myEventListener->oneFrame();
		myGUI->oneFrame();
		break;
		
		case GAME_STATE:
		myEventListener->oneFrame();
		myGUI->oneFrame();
		myAI->oneFrame();
		myWorld->oneFrame( time);
		break;
	}
}

void Game::startRendering()
{
	myRenderer->start();
}

void Game::handleEvents()
{
	while ( !myEvents.empty() )
	{
		Event evtTmp = myEvents.front();
		myEvents.pop();

		switch ( evtTmp.message ) 
		{
			case NEW_GAME:
			{
				createNewGame();

				myGUI->receiveEvent( evtTmp);
				myRenderer->receiveEvent( evtTmp);
				myEventListener->receiveEvent( evtTmp);
			}
			break;

			case CREATE_GAME_MENU:
			myState = GUI_STATE;

			myGUI->receiveEvent( evtTmp);
			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			break;

			case RETURN_GAME:
			myState = GAME_STATE;

			myGUI->receiveEvent( evtTmp);
			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			break;

			case RETURN_MENU:
			myState = MENU_STATE;

			myWorld->unloadWorld();

			myGUI->receiveEvent( evtTmp);
			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			break;

			case QUIT:
			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			break;

			case OPEN_COMPETENCE:
			myState = GUI_STATE;

			myGUI->receiveEvent( evtTmp);
			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			break;

			case OPEN_INVENTORY:
			myState = GUI_STATE;

			myGUI->receiveEvent( evtTmp);
			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			break;

			case CLOSE_INVENTORY:
			myState = GAME_STATE;

			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			break;

			case CLOSE_COMPETENCE:
			myState = GAME_STATE;

			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			break;

			case OPEN_TALK:
			myState = GUI_STATE;

			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			myGUI->receiveEvent( evtTmp);
			break;
			
			case CLOSE_GUI_WINDOW:
			myState = GAME_STATE;

			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			myGUI->receiveEvent( evtTmp);
			break;

			case CLOSE_TALK:
			myState = GAME_STATE;

			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			myGUI->receiveEvent( evtTmp);
			break;

			case OPEN_QUEST:
			myState = GUI_STATE;

			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			myGUI->receiveEvent( evtTmp);
			break;

			case CLOSE_QUEST:
			myState = GAME_STATE;

			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			myGUI->receiveEvent( evtTmp);
			break;

			case HERO_DEATH:
			myState = GUI_STATE;

			myRenderer->receiveEvent( evtTmp);
			myEventListener->receiveEvent( evtTmp);
			myGUI->receiveEvent( evtTmp);
			break;
		}
	}
}

# if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
# define WIN32_LEAN_AND_MEAN
# include "windows.h"
# endif

# ifdef __cplusplus
extern "C" {
# endif

# if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
# else
int main( int argc, char* argv[])
# endif
{
	Game* gameTmp = new Game();
	
	gameTmp->init();

	return 0;	
}

# ifdef __cplusplus
} 
# endif